/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.action.retrieve;

import com.inspur.edp.bef.api.be.IBEManagerContext;
import com.inspur.edp.bef.api.be.IBusinessEntity;
import com.inspur.edp.bef.core.action.retrieve.MultiEffectiveMgrAction.MultiEffectiveResult;
import com.inspur.edp.bef.core.be.BusinessEntity;
import com.inspur.edp.bef.spi.action.AbstractManagerAction;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.entity.changeset.ChangeType;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MultiEffectiveMgrAction extends AbstractManagerAction<MultiEffectiveResult> {

  private final String nodeCode;
  private final List<String> dataIds;
  private String propName;
  public MultiEffectiveMgrAction(IBEManagerContext managerContext,String nodeCode, java.util.List<String> dataIds)
  {
    super(managerContext);
    super.isReadOnly=true;
    this.nodeCode = nodeCode;
    this.dataIds = dataIds;
  }

  public MultiEffectiveMgrAction(IBEManagerContext managerContext,String nodeCode, java.util.List<String> dataIds, String propName)
  {
    super(managerContext);
    super.isReadOnly=true;
    this.nodeCode = nodeCode;
    this.dataIds = dataIds;
    this.propName = propName;
  }

  @Override
  public void execute() {
    ArrayList<String> notCheckedDatas = new ArrayList<>();
    ArrayList<String> notPassedDatas=new ArrayList<>();
    RefObject<ArrayList<String>> noneEffectiveDatas=new RefObject<>(notPassedDatas);
    checkInMemory(notCheckedDatas,notPassedDatas);
    if(notPassedDatas.size()>0)
      setResult(new MultiEffectiveResult(false,notPassedDatas));
    else {
      boolean checkReuslt = false;
      if(this.propName == null || this.propName.isEmpty()){
        checkReuslt = getBEManagerContext().getBEManager().getRepository()
                .isDatasEffective(nodeCode, notCheckedDatas, noneEffectiveDatas);
      }
      else {
        checkReuslt = getBEManagerContext().getBEManager().getRepository()
                .isDatasEffective(nodeCode, notCheckedDatas, noneEffectiveDatas, this.propName);
      }
      setResult(new MultiEffectiveResult(checkReuslt, noneEffectiveDatas.argvalue));
    }
  }

  private void checkInMemory(List<String> notCheckedDatas, List<String> notPassedDatas) {
    boolean isRoot = isRoot();
    if(isRoot)
    {
      checkRootsInMemory(notCheckedDatas,notPassedDatas);
    }
    else{
      notCheckedDatas.addAll(this.dataIds);
    }
  }

  private void checkRootsInMemory(List<String> notCheckedDatas,
      List<String> notPassedDatas) {
    Map<String, IBusinessEntity> entities = getBEManagerContext().getEntitiesMap(dataIds);
    if (entities == null)
      return;

    for (Map.Entry<String, IBusinessEntity> item : entities.entrySet()) {
      IChangeDetail changeDetail = item.getValue().getBEContext().getCurrentTransactionalChange();
      if (changeDetail == null)
        notCheckedDatas.add(item.getKey());
      else if(changeDetail.getChangeType()== ChangeType.Deleted)
        notCheckedDatas.add(item.getKey());
    }
  }

  private boolean isRoot() {
    return nodeCode.equals(
        (((BusinessEntity) getBEManagerContext().getBEManager().createSessionlessEntity(""))
            .getNodeCode()));
  }

  public class MultiEffectiveResult
  {
    private final boolean isEffectResult;
    private final List<String> noneEffectiveDatas;

    MultiEffectiveResult(boolean isEffectResult, List<String> noneEffectiveDatas)
    {
      this.isEffectResult = isEffectResult;
      this.noneEffectiveDatas = noneEffectiveDatas;
    }

    public boolean isEffectResult() {
      return isEffectResult;
    }

    public List<String> getNoneEffectiveDatas() {
      return noneEffectiveDatas;
    }
  }
}
